package com.daisuxia.web.controller;

import static com.daisuxia.web.pojo.BorrowOrder.STATUS_BFHK;
import static com.daisuxia.web.pojo.BorrowOrder.STATUS_HKZ;
import static com.daisuxia.web.pojo.BorrowOrder.STATUS_YHZ;
import static com.daisuxia.web.pojo.BorrowOrder.STATUS_YYQ;
import static com.daisuxia.web.pojo.BorrowOrder.borrowStatusMap_shenheFail;
import static com.daisuxia.web.pojo.BorrowOrder.borrowStatusMap_shenhezhong;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.daisuxia.allin.SybPayService;
import com.daisuxia.back.utils.ServiceResult;
import com.daisuxia.back.utils.SpringUtils;
import com.daisuxia.back.utils.SysCacheUtils;
import com.daisuxia.back.utils.WebClient;
import com.daisuxia.constant.CollectionConstant;
import com.daisuxia.constant.Constant;
import com.daisuxia.constant.FuYouConstant;
import com.daisuxia.lianlian.entity.LianlianNotifyRecv;
import com.daisuxia.lianlian.entity.LianlianSignGrantRecv;
import com.daisuxia.payRoute.PayRoute;
import com.daisuxia.risk.service.IOutOrdersService;
import com.daisuxia.web.common.reslult.JsonResult;
import com.daisuxia.web.pojo.BackConfigParams;
import com.daisuxia.web.pojo.BorrowOrder;
import com.daisuxia.web.pojo.OutOrders;
import com.daisuxia.web.pojo.Payment;
import com.daisuxia.web.pojo.RenewalRecord;
import com.daisuxia.web.pojo.Repayment;
import com.daisuxia.web.pojo.RepaymentDetail;
import com.daisuxia.web.pojo.User;
import com.daisuxia.web.pojo.UserCardInfo;
import com.daisuxia.web.pojo.fuyou.MobilePayRecv;
import com.daisuxia.web.service.IBorrowOrderService;
import com.daisuxia.web.service.IRenewalRecordService;
import com.daisuxia.web.service.IRepaymentDetailService;
import com.daisuxia.web.service.IRepaymentService;
import com.daisuxia.web.service.IUserBankService;
import com.daisuxia.web.service.IUserService;
import com.daisuxia.web.service.SequenceManagerService;
import com.daisuxia.web.util.ConfigConstant;
import com.daisuxia.web.util.DateUtil;
import com.daisuxia.web.util.GenerateNo;
import com.daisuxia.web.util.JSONUtil;
import com.daisuxia.web.util.MapConvertCoreUtils;
import com.daisuxia.web.util.PMD5Utils;
import com.daisuxia.web.util.QrCodeUtil;
import com.daisuxia.web.util.StringUtils;
import com.daisuxia.web.util.encrypt.AESUtil;
import com.daisuxia.web.util.encrypt.MD5coding;

import net.sf.json.JSONObject;
import redis.clients.jedis.JedisCluster;


/***
 * 还款
 *
 * @author Administrator
 */
@Controller
@RequestMapping("repayment/")
@SuppressWarnings("all")
public class RepaymentWebController extends BaseController {

	private static Logger logger = LoggerFactory.getLogger(RepaymentWebController.class);
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	@Autowired
	SequenceManagerService sequenceManagerService;
	@Autowired
	private IRepaymentService repaymentService;
	@Autowired
	private IRepaymentDetailService repaymentDetailService;
	@Autowired
	private IBorrowOrderService borrowOrderService;
	@Autowired
	private IUserBankService userBankService;
	@Autowired
	private IUserService userService;
	@Autowired
	private IRenewalRecordService renewalRecordService;
	@Autowired
	private IOutOrdersService outOrdersService;
	@Autowired
	private JedisCluster jedisCluster;

	//连连代扣，交易处理中key
	private static String WITHHOLD_KEYS = "REPAYMENT_REPAY_WITHHOLD";

	@RequestMapping(value = "/detailForJdq")
	public String detailForJdq(HttpServletRequest request, Model model, HttpServletResponse response) {
		Map<String, String> map = getParameters(request);
		/***借点钱回调*/
		String errorReturnUrl = map.get("errorReturnUrl");
		String successReturnUrl = map.get("successReturnUrl");
		/***借点钱回调*/
		/***融360回调*/
		String rtl = map.get("rtl");
		String idString = map.get("id");
		String url = "";
		String errMsg = null;
		try {
			Map<String, String> params = SysCacheUtils.getConfigMap(BackConfigParams.TG_SERVER);
			String id = null;
			id = AESUtil.decrypt(idString, params.get("TG_SERVER_KEY"));
			if (id != null) {
				model.addAttribute("sgd", idString);
				model.addAttribute("id", id);
				model.addAttribute("successReturnUrl", successReturnUrl);
				model.addAttribute("errorReturnUrl", errorReturnUrl);
				model.addAttribute("rtl", rtl);
				url = "redirect:/repayment/detail";
			} else {
				errMsg = "参数非法";
			}
		} catch (Exception e) {
			logger.error("detailForJdq error map=" + map, e);
		} finally {
			if (StringUtils.isNotBlank(errMsg)) {
				model.addAttribute("errMsg", errMsg);
				url = "redirect:" + errorReturnUrl;
			}
		}
		return url;
	}

	/**
	 * 还款页面跳转
	 *
	 * @param request
	 * @param model
	 * @param id
	 * @return
	 */
	@RequestMapping("detail")
	public String detail(HttpServletRequest request, Model model, Integer id) {
		String errorReturnUrl = request.getParameter("errorReturnUrl");
		String successReturnUrl = request.getParameter("successReturnUrl");
		String rtl = request.getParameter("rtl");
		String clientType = request.getParameter("clientType");
		boolean isTg = false;
		if (StringUtils.isNotBlank(errorReturnUrl)) {
			model.addAttribute("errorReturnUrl", errorReturnUrl);
			isTg = true;
		}
		if (StringUtils.isNotBlank(successReturnUrl)) {
			isTg = true;
			model.addAttribute("successReturnUrl", successReturnUrl);
		}
		if (StringUtils.isNotBlank(rtl)) {
			model.addAttribute("rtl", rtl);
			isTg = true;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		// User user = this.loginFrontUser(request);
		BorrowOrder bo = borrowOrderService.findOneBorrow(id);
		UserCardInfo info = userService.findUserBankCard(bo.getUserId());
		info.setCard_no(info.getCard_no().substring(info.getCard_no().length() - 4));
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		Map<String, String> map = new HashMap<String, String>();
		map.put("tag", "0");
		map.put("title", "申请提交成功" + dateFormat.format(bo.getCreatedAt()));
		map.put("body", "申请借款" + (bo.getMoneyAmount() / 100.00) + "元，期限" + bo.getLoanTerm() + BorrowOrder.loanMethed.get(bo.getLoanMethod()) + "，手续费"
				+ (bo.getLoanInterests() / 100.00) + "元");
		list.add(map);
		map = new HashMap<String, String>();
		// 如果是 待初审(待机审)、初审通过(机审通过)，待复审 显示审核中
		// if(bo.getStatus().equals(BorrowOrder.STATUS_DCS) ||
		// bo.getStatus().equals(BorrowOrder.STATUS_CSTG)){
		if (borrowStatusMap_shenhezhong.containsKey(bo.getStatus())) {
			map.put("tag", "1");
			map.put("title", "审核中");
			map.put("body", "已进入风控审核状态，请您耐心等待");
			list.add(map);
		}
		// 如果是 机审拒绝、初审驳回、复审驳回 显示审核不通过
		// else if(bo.getStatus().equals(BorrowOrder.STATUS_JSJJ) ||
		// bo.getStatus().equals(BorrowOrder.STATUS_CSBH) ||
		// bo.getStatus().equals(BorrowOrder.STATUS_FSBH)){
		else if (borrowStatusMap_shenheFail.containsKey(bo.getStatus())) {
			map.put("tag", "1");
			map.put("title", "审核不通过");
			// 如果是 机审拒绝、初审驳回 显示初审备注
			if (bo.getStatus().equals(BorrowOrder.STATUS_CSBH)) {
				if (bo.getVerifyTrialUser().equals("机审")) {
					map.put("body", "信用评分不足");
				} else {
					map.put("body", bo.getVerifyTrialRemark());
				}

			}
			// 如果是 复审拒绝 显示复审备注
			else if (bo.getStatus().equals(BorrowOrder.STATUS_FSBH)) {
				map.put("body", bo.getVerifyReviewRemark());
			} else if (bo.getStatus().equals(BorrowOrder.STATUS_FKBH)) {
				map.put("body", bo.getVerifyLoanRemark());
			} else {
				map.put("body", "经审核您不符合借款要求");
			}
			list.add(map);
		} else {
			map.put("tag", "0");
			map.put("title", "审核通过" + dateFormat.format(bo.getVerifyReviewTime()));
			map.put("body", "恭喜通过风控审核");
			list.add(map);
			map = new HashMap<String, String>();
			if (bo.getStatus().equals(BorrowOrder.STATUS_FSTG)) {
				map.put("tag", "1");
				map.put("title", "打款审核中");
				map.put("body", "已进入打款审核状态，请您耐心等待");
				list.add(map);
			} else if (bo.getStatus().equals(BorrowOrder.STATUS_FKZ) || bo.getStatus().equals(BorrowOrder.STATUS_FKSB)) {
				map.put("tag", "1");
				map.put("title", "打款中");
				map.put("body", "已进入打款流程，请您耐心等待");
				list.add(map);
			} else if (bo.getStatus().equals(BorrowOrder.STATUS_FKBH)) {
				map.put("tag", "1");
				map.put("title", "打款审核不通过");
				map.put("body", bo.getVerifyLoanRemark());
				list.add(map);
			}
			// else if(bo.getStatus().equals(BorrowOrder.STATUS_FKSB)){
			// map.put("tag", "1");
			// map.put("title", "打款失败");
			// map.put("body", "打款失败，详情请联系客服");
			// list.add(map);
			// }
			else {
				Map<String, Object> mapT = new HashMap<String, Object>();
				mapT.put("assetOrderId", bo.getId());
				Repayment repayment = repaymentService.findOneRepayment(mapT);

				map.put("tag", "0");
				map.put("title", "打款成功");
				map.put("body", "打款至" + info.getBankName() + "(" + info.getCard_no() + ")");
				list.add(map);
				map = new HashMap<String, String>();
				map.put("tag", "1");
				if (bo.getStatus().equals(BorrowOrder.STATUS_HKZ) || bo.getStatus().equals(BorrowOrder.STATUS_BFHK)) {
					try {
						String repayStatus = jedisCluster.get("FUYOU_REPAY_" + repayment.getId());
						String renewalStatus = jedisCluster.get("FUYOU_RENEWAL_" + repayment.getId());
						if ("true".equals(repayStatus)) {
							map.put("title", "还款提交中");
							model.addAttribute("applying", "true");
						} else if ("true".equals(renewalStatus)) {
							map.put("title", "续期提交中");
							model.addAttribute("applying", "true");
						} else {
							map.put("title", DateUtil.daysBetween(new Date(), repayment.getRepaymentTime()) + "天后还款");
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
					map.put("body", "请于" + dateFormat.format(repayment.getRepaymentTime()) + "前将还款金额存入银行卡中");
				} else if (bo.getStatus().equals(BorrowOrder.STATUS_BFHK)) {
					map.put("title", "部分还款");
					map.put("body", "请于" + dateFormat.format(repayment.getRepaymentTime()) + "前将还款金额存入银行卡中");
				} else if (bo.getStatus().equals(BorrowOrder.STATUS_YYQ)) {
					map.put("title", "已逾期");
					map.put("body", "您的借款已逾期，请尽快完成还款操作");
				} else if (bo.getStatus().equals(BorrowOrder.STATUS_YHZ)) {
					map.put("title", "已坏账");
					map.put("body", "您的借款已坏账，详情请联系客服");
				} else {// if(bo.getStatus().equals(BorrowOrder.STATUS_YHK))
					map.put("title", "已还款");
					map.put("body", "恭喜还款成功，又积攒了一份信用");
				}
				list.add(map);
				model.addAttribute("repayment", repayment);
			}
		}
		model.addAttribute("list", list);
		model.addAttribute("info", info);
		model.addAttribute("clientType",clientType);
		model.addAttribute("bo", bo);
		model.addAttribute("appName", request.getParameter("appName"));
		/*
		 * try { HashMap<String, Object> params = getParametersO(request);
		 * params.put("noAdmin", Constant.ADMINISTRATOR_ID);
		 * params.put("statuses", statuses); PageConfig<Repayment> pageConfig =
		 * repaymentService.findPage(params); model.addAttribute("pm",
		 * pageConfig); model.addAttribute("params", params);// 用于搜索框保留值
		 * 
		 * } catch (Exception e) { logger.error("getRepaymentPage error", e); }
		 */
		if (isTg) {
			model.addAttribute("sgd", request.getParameter("sgd"));
			return "repayment/tg/repaymentDetail2";
		}
		return "repayment/repaymentDetail";
	}

	/**
	 * 还款页面跳转
	 *
	 * @param request
	 * @param model
	 * @param id
	 * @return
	 */
	@RequestMapping("repay-choose")
	public String repayChoose(HttpServletRequest request, Model model, Integer id) {
		BorrowOrder bo = borrowOrderService.findOneBorrow(id);
		UserCardInfo info = userService.findUserBankCard(bo.getUserId());
		info.setCard_no(info.getCard_no().substring(info.getCard_no().length() - 4));
		model.addAttribute("info", info);
		model.addAttribute("bo", bo);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("assetOrderId", bo.getId());
		Repayment repayment = repaymentService.findOneRepayment(map);
		model.addAttribute("repayment", repayment);
		return "repayment/repaymentChoose";
	}

	/**
	 * 还款方式页面
	 *
	 * @param request
	 * @param model
	 * @param id
	 * @return
	 */
	@RequestMapping("repay-type")
	public String repayType(HttpServletRequest request, Model model, Integer id) {
		model.addAttribute("id", id);
		return "repayment/repaymentType";
	}

	/**
	 * 还款页面跳转
	 *
	 * @param request
	 * @param model
	 * @param id
	 * @return
	 */
	@RequestMapping("detail/{id}")
	public String detailBack(HttpServletRequest request, HttpServletResponse response, Model model, @PathVariable Integer id, LianlianSignGrantRecv ll) {
		// SpringUtils.renderJson(response,
		// "{'ret_code':'0000','ret_msg':'交易成功'}");
		return detail(request, model, id);
	}

	// 连连代扣回调
	@RequestMapping("debit-back")
	public void debitBack(HttpServletRequest request, HttpServletResponse response) {
		Integer repayId = 0;
		try {
			byte buffer[] = getRequestPostBytes(request);
			String charEncoding = request.getCharacterEncoding();
			if (charEncoding == null) {
				charEncoding = "UTF-8";
			}
			if (null == buffer) {
				logger.error("debitBack error buffer is null");
				SpringUtils.renderJson(response, "{'ret_code':'100','ret_msg':'交易失败'}");
				return;
			}
			String alipays = new String(buffer, charEncoding);
			logger.error("debit-back object=" + alipays);
			LianlianNotifyRecv notifyRecv = JSONUtil.jsonToBean(alipays, LianlianNotifyRecv.class);
			SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMdd");
			if (null != notifyRecv && null != notifyRecv.getNo_order()) {
				OutOrders outOrders = outOrdersService.findByOrderNo(notifyRecv.getNo_order());
				logger.error("debit-back no_order=" + notifyRecv.getNo_order() + "outOrder status=" + (null != outOrders ? outOrders.getStatus() : "null") + " assOrderId=" + (null != outOrders ? outOrders.getAssetOrderId() : "null"));
				if (null != outOrders && (!OutOrders.STATUS_SUC.equals(outOrders.getStatus()))) {
					if (null != outOrders.getAssetOrderId()) {
						if ("SUCCESS".equals(notifyRecv.getResult_pay())) {
							logger.error("debit-back success no_order=" + notifyRecv.getNo_order());
							long money_order = (long) Double.parseDouble(notifyRecv.getMoney_order()) * 100;
							RepaymentDetail detail = repaymentDetailService.selectByOrderId(outOrders.getOrderNo());
							Repayment re = repaymentService.selectByPrimaryKey(outOrders.getAssetOrderId());
							repayId = re.getId();
							if (null != detail) {
								logger.error("repaymentWeb debit-back detail 查到了============ outOrder=" + outOrders.getOrderNo() + " detailId=" + detail.getId());
								if (RepaymentDetail.STATUS_SUC != detail.getStatus()) {
									detail.setStatus(RepaymentDetail.STATUS_SUC);
									repaymentService.repay(re, detail);
								}
							} else {
								logger.error("repaymentWeb debit-back detail 查不到------- outOrder=" + outOrders.getOrderNo());
								if (StringUtils.isNotBlank(outOrders.getNotifyParams())) {
									String[] withholdIds = outOrders.getNotifyParams().split("\\|\\|");
									if (withholdIds.length > 1) {
										re.setWithholdId(withholdIds[1]);
									}
								}
								detail = new RepaymentDetail();
								detail.setUserId(re.getUserId());
								detail.setAssetRepaymentId(re.getId());
								detail.setTrueRepaymentMoney(money_order);

								detail.setCreatedAt(format1.parse(notifyRecv.getSettle_date()));
								detail.setOrderId(notifyRecv.getOid_paybill());
								detail.setRepaymentType(RepaymentDetail.TYPE_BANK_CARD_AUTO);
								detail.setRemark("代扣回调");
								detail.setUserId(re.getUserId());
								detail.setUpdatedAt(new Date());
								detail.setStatus(RepaymentDetail.STATUS_SUC);
								detail.setAssetOrderId(re.getAssetOrderId());
								repaymentDetailService.insertSelective(detail);
								repaymentService.repay(re, detail);
							}
							outOrders.setStatus(OutOrders.STATUS_SUC);
						} else {
							outOrders.setStatus(OutOrders.STATUS_OTHER);

						}
						outOrders.setReturnParams(alipays);
						outOrdersService.updateByOrderNo(outOrders);
					} else {
						SpringUtils.renderJson(response, "{'ret_code':'100','ret_msg':'交易失败'}");
					}
					logger.error("debit-back assetOrderId=" + outOrders.getAssetOrderId() + ",status" + outOrders.getStatus());
				}
			}
			//交易成功或者失败，删除锁定的该笔还款订单，防止其他渠道不能还款
			jedisCluster.del(WITHHOLD_KEYS + "_" + repayId);
			SpringUtils.renderJson(response, "{'ret_code':'0000','ret_msg':'交易成功'}");
		} catch (Exception e) {
			logger.error("debit-back error", e);
			SpringUtils.renderJson(response, "{'ret_code':'100','ret_msg':'交易失败'}");
		}
	}

	public static byte[] getRequestPostBytes(HttpServletRequest request) throws IOException {
		int contentLength = request.getContentLength();
		if (contentLength < 0) {
			return null;
		}
		byte buffer[] = new byte[contentLength];
		for (int i = 0; i < contentLength; ) {

			int readlen = request.getInputStream().read(buffer, i, contentLength - i);
			if (readlen == -1) {
				break;
			}
			i += readlen;
		}
		return buffer;
	}

	/**
	 * 扫码支付页面
	 *
	 * @param request
	 * @param model
	 * @param id
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping("repay-type-sao")
	public String repaymentTypeSao(HttpServletRequest request, HttpServletResponse response ,Model model, Integer id) throws Exception {
		String userId = request.getParameter("userId");
		User user = userService.searchByUserid(Integer.parseInt(userId));
		List<Repayment> res = repaymentService.findAllByBorrowId(id);
		if(null!=res && null!=res.get(0)) {
			Repayment repayment = res.get(0);
			if(null!=repayment&&repayment.getStatus()!=BorrowOrder.STATUS_YHK) {
				//Long amt = repayment.getRepaymentAmount()-repayment.getRepaymentedAmount();
				
				//-------------测试代码------------------
				Long amt = 1L;
				
				//微信付款码
				String wxcodeUrl = ConfigConstant.getConstant("SAO_IMAGE_URL_PREFIX");//当前请求微信支付二维码请求地址
				String wxSaoImageUri = jedisCluster.get(Constant.PAY_WX_SAO_PREFIX+repayment.getId());
				if(null==wxSaoImageUri) {
					//发起第三方支付
					Long orderNo =sequenceManagerService.getNewId();
					Map<String, String> map = SybPayService.pay(amt, orderNo.toString(), "W01", "还款", "微信扫码还款", "60");
					if(null!=map&&"SUCCESS".equals(map.get("retcode"))) {
						//生成待还款订单
						RepaymentDetail detail = new RepaymentDetail();
						detail.setAssetRepaymentId(repayment.getId());
						detail.setTrueRepaymentMoney(amt);
						detail.setRepaymentType(RepaymentDetail.TYPE_WX_SAO);
						detail.setUserId(repayment.getUserId());
						detail.setCreatedAt(new Date());
						detail.setAssetOrderId(repayment.getAssetOrderId());
						detail.setOrderId(orderNo.toString());
						detail.setStatus(RepaymentDetail.STATUS_WAIT);
						repaymentDetailService.insertSelective(detail);
						//生成图片并返回
						String payinfo = map.get("payinfo");
						String datestr = sdf.format(new Date());
						String imgUri = "/allinpay/"+datestr+"/"+repayment.getId()+"_wx_"+amt/new Double(100)+".jpg";//redis的值(真正文件地址allinpay/后面的目录结构)
						String filepath = ConfigConstant.getConstant("QRCDE_FILEPATH")+imgUri;
						File qrcodeFile = new File(filepath);
						if(!qrcodeFile.exists())//如果没有文件则新建一个
							qrcodeFile.mkdirs();
						QrCodeUtil.encode(payinfo, 300, 300, ConfigConstant.getConstant("WX_PNG_FILEPATH"), filepath);//生成二维码存到本地
						jedisCluster.setex(Constant.PAY_WX_SAO_PREFIX+repayment.getId(), 60*60,imgUri);//保存到redis
						wxcodeUrl=wxcodeUrl+imgUri;
					}
				}else {
					wxcodeUrl=wxcodeUrl+wxSaoImageUri;
				}
				model.addAttribute("wxcodeUrl", wxcodeUrl);
				model.addAttribute("wxMoney", wxcodeUrl.substring(wxcodeUrl.lastIndexOf("_")+1, wxcodeUrl.lastIndexOf(".")));
				logger.info("wxcodeUrl"+wxcodeUrl);
				//支付宝付款码
				String alipaycodeUrl = ConfigConstant.getConstant("SAO_IMAGE_URL_PREFIX");//当前请求支付宝支付二维码请求地址
				String aliPaySaoImageUri = jedisCluster.get(Constant.PAY_ALIPAY_SAO_PREFIX+repayment.getId());
				if(null==aliPaySaoImageUri) {
					//发起第三方支付
					Long orderNo =sequenceManagerService.getNewId();
					Map<String, String> map = SybPayService.pay(amt, orderNo.toString(), "A01", "还款", "支付宝扫码还款", "60");
					if(null!=map&&"SUCCESS".equals(map.get("retcode"))) {
						//生成待还款订单
						RepaymentDetail detail = new RepaymentDetail();
						detail.setAssetRepaymentId(repayment.getId());
						detail.setTrueRepaymentMoney(amt);
						detail.setRepaymentType(RepaymentDetail.TYPE_ALIPAY_SAO);
						detail.setUserId(repayment.getUserId());
						detail.setCreatedAt(new Date());
						detail.setAssetOrderId(repayment.getAssetOrderId());
						detail.setOrderId(orderNo.toString());
						detail.setStatus(RepaymentDetail.STATUS_WAIT);
						repaymentDetailService.insertSelective(detail);
						//生成图片并返回
						String payinfo = map.get("payinfo");
						String datestr = sdf.format(new Date());
						String imgUri = "/allinpay/"+datestr+"/"+repayment.getId()+"_alipay_"+new Double(amt/new Double(100))+".jpg";//redis的值(真正文件地址allinpay/后面的目录结构)
						String filepath = ConfigConstant.getConstant("QRCDE_FILEPATH")+imgUri;
						File qrcodeFile = new File(filepath);
						if(!qrcodeFile.exists())//如果没有文件则新建一个
							qrcodeFile.mkdirs();
						QrCodeUtil.encode(payinfo, 300, 300, ConfigConstant.getConstant("ALIPAY_PNG_FILEPATH"), filepath);//生成
						jedisCluster.setex(Constant.PAY_ALIPAY_SAO_PREFIX+repayment.getId(), 60*60,imgUri);
						alipaycodeUrl=alipaycodeUrl+imgUri;
					}
				}else {
					alipaycodeUrl=alipaycodeUrl+aliPaySaoImageUri;
				}
				model.addAttribute("alipaycodeUrl", alipaycodeUrl);
				model.addAttribute("alipayMoney", alipaycodeUrl.substring(alipaycodeUrl.lastIndexOf("_")+1, alipaycodeUrl.lastIndexOf(".")));
				logger.info("alipaycodeUrl"+alipaycodeUrl);
			}
		}
		model.addAttribute("realname", user.getRealname());
		model.addAttribute("phone", user.getUserPhone());
		return "repayment/repaymentTypeAlipay";
	}


	/**
	 * 银行卡主动支付
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping("repay-bank-card")
	public void repaymentBankCard(HttpServletResponse response, HttpServletRequest request, Integer id, String payPwd) {
		try {
			BorrowOrder bo = borrowOrderService.findOneBorrow(id);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("assetOrderId", bo.getId());
			Repayment re = repaymentService.findOneRepayment(map);
			User user = userService.searchByUserid(bo.getUserId());
			UserCardInfo info = userService.findUserBankCard(bo.getUserId());
			AESUtil aesEncrypt = new AESUtil();
			//String repayStatus = jedisCluster.get("FUYOU_REPAY_" + re.getId());
			String repayStatus = jedisCluster.get("REPAYMENT_REPAY_WITHHOLD_" + re.getId());
			JsonResult rest = null;
			if("true".equals(repayStatus)) {
				rest = new JsonResult("-101", "您有还款处于支付中，请稍后尝试");
			} else if (null == user.getPayPassword()) {
				rest = new JsonResult("-101", "请从个人中心完善支付密码");
			} else if (!STATUS_HKZ.equals(re.getStatus()) && !STATUS_BFHK.equals(re.getStatus()) && !STATUS_YYQ.equals(re.getStatus())
					&& !STATUS_YHZ.equals(re.getStatus())) {
				rest = new JsonResult("-101", "本条还款不支持还款");
			} else {
				boolean isPass = false;
				String sgd = request.getParameter("sgd");
				if (StringUtils.isNotBlank(sgd)) {
					Map<String, String> params = SysCacheUtils.getConfigMap(BackConfigParams.TG_SERVER);
					sgd = AESUtil.decrypt(sgd, params.get("TG_SERVER_KEY"));
					if (String.valueOf(id).equals(sgd)) {
						isPass = true;
					} else {
						rest = new JsonResult("-101", "参数非法！");
					}
				} else {
					if (user.getPayPassword().equals(MD5coding.MD5(aesEncrypt.encrypt(payPwd, "")))) {
						isPass = true;
					} else {
						rest = new JsonResult("-103", "支付密码输入错误");
					}
				}
				if (isPass) {
					//设置支付锁
					//锁定该笔还款，防止其他渠道再次扣款 5分钟之类有效
					jedisCluster.set("REPAYMENT_REPAY_WITHHOLD_"+re.getId(),"true");
					RepaymentDetail detail = new RepaymentDetail();
					detail.setAssetRepaymentId(re.getId());
					detail.setTrueRepaymentMoney(re.getRepaymentAmount() - re.getRepaymentedAmount());
					detail.setRepaymentType(RepaymentDetail.TYPE_BANK_CARD);
					detail.setUserId(bo.getUserId());
					detail.setCreatedAt(new Date());
					detail.setAssetOrderId(re.getAssetOrderId());
					detail.setCardId(info.getId());
					String unique_mark = GenerateNo.getUUID();
					detail.setOrderId(unique_mark);
					detail.setStatus(RepaymentDetail.STATUS_WAIT);
					repaymentDetailService.insertSelective(detail);
					

					//计算实际应该金额（还款表：总金额 - 实际还款金额）
					Long money =re.getRepaymentAmount() - re.getRepaymentedAmount();
					//由原来的访问支付路由改为 访问P2P接口，由P2P进行扣款
					Map result = P2PDeduct(String.valueOf(bo.getOutTradeNo()), money,money, unique_mark);
					if (null != result || result.size() != 0) {
						String errorcode = result.get("errorcode")==null?"":result.get("errorcode").toString();//错误码
						String errormsg = result.get("errormsg")==null?"":result.get("errormsg").toString();//错误描述
						if ("10021".equals(errorcode)) {
							rest = new JsonResult("-101", "当前单号错误或不存在");
						}
						if ("10023".equals(errorcode)) {
							rest = new JsonResult("-101", "已提交还款处理,请耐心等待");
						}
						if ("10024".equals(errorcode)) {
							rest = new JsonResult("-101", "当前单号还款类型错误，建议您联系客服");
						}
						if ("10025".equals(errorcode)) {
							rest = new JsonResult("-101", "当前订单已还款成功,无需重复提交");
						}
						if ("10030".equals(errorcode)) {
							rest = new JsonResult("-101", "当前订单已在处理中，请稍后");
						}
						if ("0".equals(errorcode) && !"".equals(result.get("dataresult"))) {
							JSONObject dataresult = JSONObject.fromObject(result.get("dataresult"));
							if (dataresult.containsKey("sn") && dataresult.containsKey("msg") &&
									!"".equals(dataresult.getString("sn")) && !"".equals(dataresult.getString("msg"))) {
								rest = new JsonResult("-101", "已提交还款处理,请耐心等待");
								//将P2P返回的sn（交易订单号）存储到订单表（asset_borrow_order）yurref字段（招行订单号）
								BorrowOrder borrowOrder = new BorrowOrder();
								borrowOrder.setId(bo.getId());
								borrowOrder.setYurref(dataresult.getString("sn"));
								borrowOrderService.updateById(borrowOrder);
							}
						}
					}
				}
			}
			SpringUtils.renderJson(response, rest);
		} catch (Exception e) {
			e.printStackTrace();
			JsonResult rest = new JsonResult("-101", "系统异常");
			SpringUtils.renderJson(response, rest);
		}

	}

	/**
	 * 续期页面
	 *
	 * @param request
	 * @param model
	 * @param id
	 * @return
	 */
	@RequestMapping("renewal")
	public String renewal(HttpServletRequest request, Model model, Integer id) {
		String errorReturnUrl = request.getParameter("errorReturnUrl");
		String successReturnUrl = request.getParameter("successReturnUrl");
		String rtl = request.getParameter("rtl");
		boolean isTg = false;
		if (StringUtils.isNotBlank(errorReturnUrl)) {
			model.addAttribute("errorReturnUrl", errorReturnUrl);
			isTg = true;
		}
		if (StringUtils.isNotBlank(successReturnUrl)) {
			model.addAttribute("successReturnUrl", successReturnUrl);
			isTg = true;
		}
		if (StringUtils.isNotBlank(rtl)) {
			model.addAttribute("rtl", rtl);
			isTg = true;
		}
		Map<String, String> keys = SysCacheUtils.getConfigParams(BackConfigParams.SYS_FEE);
		// 续期费
		String renewalFee = keys.get("renewal_fee");

		BorrowOrder bo = borrowOrderService.findOneBorrow(id);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("assetOrderId", bo.getId());
		Repayment re = repaymentService.findOneRepayment(map);
		// 待还总金额
		Long waitRepay = re.getRepaymentAmount() - re.getRepaymentedAmount();
		// 待还滞纳金
		Long waitLate = Long.parseLong(String.valueOf(re.getPlanLateFee() - re.getTrueLateFee()));
		// 待还本金
		Long waitAmount = waitRepay - waitLate;
		// 服务费
		Integer loanApr = bo.getMoneyAmount() * bo.getApr() / 10000; // 服务费
		Long allCount = waitLate + loanApr + Long.parseLong(renewalFee);

		model.addAttribute("bo", bo);
		model.addAttribute("waitAmount", waitAmount);
		model.addAttribute("loanApr", loanApr);
		model.addAttribute("renewalFee", renewalFee);
		model.addAttribute("waitLate", waitLate);
		model.addAttribute("allCount", allCount);
		if (isTg) {
			model.addAttribute("sgd", request.getParameter("sgd"));
			return "repayment/tg/renewalRenewal2";
		}
		return "repayment/renewalRenewal";
	}

	/**
	 * 是否能续期
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping("renewal-whether")
	public void renewalWhether(HttpServletResponse response, Integer id) {
		try {
			JsonResult rest;

			Repayment re = repaymentService.selectByPrimaryKey(id);
			// Map<String, Object> map =
			// repaymentService.findBorrowLoanTerm(re.getAssetOrderId());
			/*
			 * if(re.getRenewalCount() >=
			 * Integer.parseInt(ConfigConstant.getConstant(Constant.RENEWAL_MAX,
			 * "2"))){ rest = new JsonResult("-100", "您的申请续期次数已上限"); } else
			 * if(null != map.get("loanTerm") &&
			 * !map.get("loanTerm").toString().equals("7")){ rest = new
			 * JsonResult("-100", "只能续期7日借款"); } else
			 */
			if (re.getStatus().equals(BorrowOrder.STATUS_YYQ) || re.getStatus().equals(BorrowOrder.STATUS_YHZ)) {
				rest = new JsonResult("-101", "该订单已逾期不能续期操作");
			} else if (re.getRepaymentedAmount() - re.getRepaymentPrincipal() - re.getRepaymentInterest() > 0) {
				rest = new JsonResult("-102", "您的本金已还完，不能继续申请续期");
			} else {
				rest = new JsonResult("0", "续期成功");
			}
			SpringUtils.renderJson(response, rest);
		} catch (Exception e) {
			e.printStackTrace();
			JsonResult rest = new JsonResult("-100", "系统异常");
			SpringUtils.renderJson(response, rest);
		}

	}

	/**
	 * 银行卡支付续期费
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping("repay-renewal")
	public void repaymentRenewal(HttpServletResponse response, HttpServletRequest request, Model model, Integer id, String payPwd, Long money) {
		JsonResult rest = new JsonResult("-101", "系统异常");
		try {
			PayRoute payRoute = new PayRoute(outOrdersService);
			String errorReturnUrl = request.getParameter("errorReturnUrl");
			String successReturnUrl = request.getParameter("successReturnUrl");
			String rtl = request.getParameter("rtl");
			Map<String, String> keys = SysCacheUtils.getConfigParams(BackConfigParams.SYS_FEE);
			// 续期费
			String renewalFee = keys.get("renewal_fee");

			BorrowOrder bo = borrowOrderService.findOneBorrow(id);

			Map<String, Object> map = new HashMap<String, Object>();
			map.put("assetOrderId", bo.getId());
			Repayment re = repaymentService.findOneRepayment(map);
			// 待还总金额
			Long waitRepay = re.getRepaymentAmount() - re.getRepaymentedAmount();
			// 待还滞纳金
			Long waitLate = Long.parseLong(String.valueOf(re.getPlanLateFee() - re.getTrueLateFee()));
			// 待还本金
			Long waitAmount = waitRepay - waitLate;
			// 服务费
			Integer loanApr = bo.getMoneyAmount() * bo.getApr() / 10000; // 服务费
			Long allCount = waitLate + loanApr + Long.parseLong(renewalFee);



			User user = userService.searchByUserid(bo.getUserId());
			UserCardInfo info = userService.findUserBankCard(bo.getUserId());
			AESUtil aesEncrypt = new AESUtil();
			 if (null == user.getPayPassword()) {
				rest = new JsonResult("-103", "请从个人中心完善支付密码");
			} else if (!STATUS_HKZ.equals(re.getStatus()) && !STATUS_BFHK.equals(re.getStatus()) && !STATUS_YYQ.equals(re.getStatus())
					&& !STATUS_YHZ.equals(re.getStatus())) {
				rest = new JsonResult("-101", "本条还款不支持还款");
			} else if (!allCount.equals(money)) {
				rest = new JsonResult("-101", "您的费用已更新，请刷新当前页面");
			} else {
				boolean isPass = false;
				String sgd = request.getParameter("sgd");
				if (StringUtils.isNotBlank(sgd)) {
					Map<String, String> params = SysCacheUtils.getConfigMap(BackConfigParams.TG_SERVER);
					sgd = AESUtil.decrypt(sgd, params.get("TG_SERVER_KEY"));
					if (String.valueOf(id).equals(sgd)) {
						isPass = true;
					} else {
						rest = new JsonResult("-101", "参数非法！");
					}
				} else {
					if (user.getPayPassword().equals(MD5coding.MD5(aesEncrypt.encrypt(payPwd, "")))) {
						isPass = true;
					} else {
						rest = new JsonResult("-103", "支付密码输入错误");
					}
				}
				if (isPass) {
					String orderNo = "";
					// 续期信息
					RenewalRecord rr = new RenewalRecord();
					rr.setUserId(re.getUserId());
					rr.setAssetRepaymentId(re.getId());
					rr.setRepaymentPrincipal(waitAmount);
					rr.setSumFee(allCount);
					rr.setRepaymentInterest((long) loanApr);
					rr.setPlanLateFee(waitLate.intValue());
					rr.setRenewalFee(Integer.valueOf(renewalFee));
					rr.setOldRepaymentTime(re.getRepaymentTime());
					rr.setRenewalDay(bo.getLoanTerm());
					rr.setStatus(RenewalRecord.STATUS_PAYING);
					rr.setMoneyAmount(re.getRepaymentPrincipal() + re.getRepaymentInterest());
					rr.setRepaymentTime(DateUtil.addDay(re.getRepaymentTime(), bo.getLoanTerm()));
					//设置手续费
					re.setRepaymentAmount(allCount);
					re.setRepaymentedAmount(0L);

					Map params = new HashMap();//请求参数
					params.put("repayment", re);//借款信息
					params.put("user", user);//用户
					params.put("userCardInfo", info);//银行卡信息
					Map result = payRoute.getCutPay(params);
					String retCode = result.get("resp_code").toString();// 返回码
					String ourOrders = result.get("payCutType").toString();//代扣方式
					String signParam = result.get("qbm_signParam").toString();//请求参数
					List errorCodes = (List) result.get("errorCodes");//错误码
					orderNo = result.get("orderNo").toString();

					rr.setOrderId(orderNo);
					OutOrders orders = new OutOrders();
					renewalRecordService.insertSelective(rr);
					orders.setOrderNo(orderNo);
					rr.setRemark(ourOrders);

					if("0000".equals(retCode)){
						rr.setStatus(RenewalRecord.STATUS_SUCC);
						repaymentService.renewal(null, rr);
						orders.setStatus(OutOrders.STATUS_SUC);
						rest = new JsonResult("0", "续期成功");
					}else if(errorCodes.contains(retCode)) {
						orders.setStatus(OutOrders.STATUS_WAIT);
						rest = new JsonResult("-101", "续期处理中,如果处理事件过长请联系客服");
					}else{
						rest = new JsonResult("-101","续期失败");
						orders.setStatus(OutOrders.STATUS_OTHER);
						rr.setStatus(RenewalRecord.STATUS_FAIL);
						renewalRecordService.updateByPrimaryKeySelective(rr);
					}
					outOrdersService.updateByOrderNo(orders);


				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		SpringUtils.renderJson(response, rest);

	}

	/**
	 * 续期富友回调
	 *
	 * @param payRecv
	 * @return
	 */
	@RequestMapping("renewal-back/{recordId}")
	public void renewalBack(MobilePayRecv payRecv, @PathVariable int recordId, HttpServletResponse response) {
		if (payRecv.toSign().equals(payRecv.getSIGN())) {
			OutOrders outOrders = outOrdersService.findByOrderNo(payRecv.getMCHNTORDERID());
			if (null != outOrders && (!OutOrders.STATUS_SUC.equals(outOrders.getStatus()))) {
				RenewalRecord record = renewalRecordService.selectByPrimaryKey(recordId);
				try {
					jedisCluster.del("FUYOU_RENEWAL_" + record.getAssetRepaymentId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (null != record) {
					OutOrders orders = new OutOrders();
					orders.setOrderNo(payRecv.getMCHNTORDERID());
					orders.setReturnParams(JSONObject.fromObject(payRecv).toString());
					if (FuYouConstant.SUCCESS_CODE.equals(payRecv.getRESPONSECODE())) {
						repaymentService.renewal(null, record);
						record.setStatus(RenewalRecord.STATUS_SUCC);
						orders.setStatus(OutOrders.STATUS_SUC);
					} else {
						orders.setStatus(OutOrders.STATUS_OTHER);
						record.setStatus(RenewalRecord.STATUS_FAIL);
						renewalRecordService.updateByPrimaryKeySelective(record);
					}
					outOrdersService.updateByOrderNo(orders);
				}
			}
		}
		SpringUtils.renderJson(response, "200");

	}

	/**
	 * 还款富友回调
	 *
	 * @param detailId
	 * @param payRecv
	 * @return
	 */
	@RequestMapping("repay-back/{detailId}")
	public void repayBack(MobilePayRecv payRecv, @PathVariable int detailId, HttpServletResponse response) {
		if (payRecv.toSign().equals(payRecv.getSIGN())) {
			OutOrders outOrders = outOrdersService.findByOrderNo(payRecv.getMCHNTORDERID());
			if (null != outOrders && (!OutOrders.STATUS_SUC.equals(outOrders.getStatus()))) {
				RepaymentDetail de = repaymentDetailService.selectByPrimaryKey(detailId);
				if (null != de) {
					RepaymentDetail detail = new RepaymentDetail();
					detail.setId(detailId);
					detail.setOrderId(payRecv.getMCHNTORDERID());

					OutOrders orders = new OutOrders();
					orders.setOrderNo(payRecv.getMCHNTORDERID());
					orders.setReturnParams(JSONObject.fromObject(payRecv).toString());
					if (FuYouConstant.SUCCESS_CODE.equals(payRecv.getRESPONSECODE())) {
						Repayment re = repaymentService.selectByPrimaryKey(de.getAssetRepaymentId());

						detail.setStatus(RepaymentDetail.STATUS_SUC);
						orders.setStatus(OutOrders.STATUS_SUC);

						repaymentService.repay(re, de);

						// 如果是未逾期的还款，调用提额
						if (re.getLateDay() == 0) {
							User user = userService.searchByUserid(re.getUserId());
							logger.error("repay to Mention Money ing ----------------->");
							borrowOrderService.addUserLimit(user);
						}
					} else {
						detail.setStatus(RepaymentDetail.STATUS_OTHER);
						orders.setStatus(OutOrders.STATUS_OTHER);
					}
					repaymentDetailService.updateByPrimaryKeySelective(detail);
					outOrdersService.updateByOrderNo(orders);
				}
				try {
					jedisCluster.del("FUYOU_REPAY_" + de.getAssetRepaymentId());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		SpringUtils.renderJson(response, "200");
	}

	// 催收代扣
	@RequestMapping("withhold/{id}/{repaymentId}/{money}/{withholdId}/{sign}")
	public void withhold(HttpServletResponse response, @PathVariable Integer id, @PathVariable Integer repaymentId, @PathVariable Long money,
						 @PathVariable String withholdId, @PathVariable String sign) {
		JsonResult rest;
		String key = "REPAYMENT_WITHHOLD_TIME_" + repaymentId;
		String lastTime = jedisCluster.get(key);
		long nowTime = new Date().getTime();
		
		String redis_repay_id = jedisCluster.get("REPAYMENT_REPAY_WITHHOLD_" + repaymentId);
		if ("true".equals(redis_repay_id)) {
			rest = new JsonResult("-100", "代扣失败,交易处理中");
		} else if (null == lastTime || (nowTime - Long.parseLong(lastTime)) >= (5 * 60 * 1000)) {
			try {
				if (MD5coding.MD5(AESUtil.encrypt("" + id + repaymentId + money + withholdId, CollectionConstant.getCollectionSign())).equals(sign)) {
					logger.info("催收代扣开始，参数："+"id"+id+"repaymentId"+repaymentId+"money"+money+"withholdId"+withholdId);
					//锁定该笔还款，防止其他渠道重复扣款
					jedisCluster.set(key, String.valueOf(nowTime));
					jedisCluster.setex("REPAYMENT_REPAY_WITHHOLD_" + repaymentId,5 * 60 ,"true");
					Repayment re = repaymentService.selectByPrimaryKey(repaymentId);
					re.setWithholdId(withholdId);
					User user = userService.searchByUserid(id);
					if (money <= 0) {
						rest = new JsonResult("-101", "代扣失败,催收金额为空");
					} else if (money > re.getRepaymentAmount() - re.getRepaymentedAmount()) {
						rest = new JsonResult("-101", "代扣失败,催收金额大于剩余待付金额");
					} else {
						ServiceResult result = repaymentService.withhold(re, user, Repayment.COLLECTION_WITHHOLD, money, OutOrders.ACT_DEBIT);
						if (result.getCode().equals(ServiceResult.SUCCESS)) {
							rest = new JsonResult("0", "代扣成功");
						} else {
							rest = new JsonResult(result.getCode(), result.getMsg());
						}
					}

					//如果处理状态码！= 100(交易处理中)，删除redis中的该笔还款的key，防止其他渠道不能还款
					if (!"100".equals(rest.getCode())) {
						jedisCluster.del("REPAYMENT_REPAY_WITHHOLD_" + repaymentId);
					}
				} else {
					rest = new JsonResult("-101", "参数有误");
					logger.error("催收代扣 param error withhold userId=" + id + " repaymentId=" + repaymentId + " money=" + money + " withholdId="
							+ withholdId + " sign= " + sign + " mysign=" + CollectionConstant.getCollectionSign());
				}
			} catch (Exception e) {
				rest = new JsonResult("-102", "系统错误");
				logger.error("催收代扣 end withhold exception userId=" + id, e);
			}
			logger.error("催收代扣 end withhold userId=" + id + " repaymentId=" + repaymentId + " code=" + rest.getCode());
		} else {
			logger.error("催收代扣 time error withhold userId=" + id + " repaymentId=" + repaymentId + " now=" + nowTime + " lastTime=" + lastTime);
			rest = new JsonResult("-103", "距离上次代扣时间不足5分钟，请稍后再试");
		}
		SpringUtils.renderJson(response, rest);
	}

	// 催收减免回调
	@RequestMapping("mitigate/{userId}/{repaymentId}/{money}/{mitigateId}/{sign}")
	public void mitigate(HttpServletResponse response, @PathVariable Integer userId, @PathVariable Integer repaymentId, @PathVariable Long money,
						 @PathVariable String mitigateId, @PathVariable String sign) {
		JsonResult rest;
		try {
			if (MD5coding.MD5(AESUtil.encrypt("" + userId + repaymentId + money + mitigateId, CollectionConstant.getCollectionSign())).equals(sign)) {
				Repayment re = repaymentService.selectByPrimaryKey(repaymentId);
				//re.setWithholdId(mitigateId);
				//User user = userService.searchByUserid(userId);
				if (money <= 0) {
					rest = new JsonResult("-101", "减免失败,减免金额为空");
				} else if (re.getRepaymentedAmount() < (re.getRepaymentPrincipal() + re.getRepaymentInterest())) {
					rest = new JsonResult("-101", "减免失败,本金未还清");
				} else if ((re.getRepaymentedAmount() + money) > re.getRepaymentAmount()) {
					rest = new JsonResult("-101", "减免失败,减免金额超出剩余应还金额");
				} else {
					RepaymentDetail detail = new RepaymentDetail();
					detail.setUserId(userId);
					detail.setAssetRepaymentId(repaymentId);
					detail.setTrueRepaymentMoney(money);
					detail.setCreatedAt(new Date());
					detail.setRepaymentType(RepaymentDetail.TYPE_OFF_LINE_DEDUCTION);
					detail.setRemark("催收减免");
					detail.setUserId(userId);
					detail.setUpdatedAt(new Date());
					detail.setStatus(RepaymentDetail.STATUS_SUC);
					detail.setAssetOrderId(re.getAssetOrderId());
					repaymentDetailService.insertSelective(detail);
					repaymentService.repay(re, detail);
					rest = new JsonResult("0", "减免成功");
				}
			} else {
				rest = new JsonResult("-101", "参数有误");
				logger.error("催收减免 param error mitigateId userId=" + userId + " repaymentId=" + repaymentId + " money=" + money + " withholdId="
						+ mitigateId + " sign= " + sign + " mysign=" + CollectionConstant.getCollectionSign());
			}
		} catch (Exception e) {
			rest = new JsonResult("-100", "系统错误");
			logger.error("", e);
		}
		logger.error("催收减免 end mitigate userId=" + userId + " repaymentId=" + repaymentId + " code=" + rest.getCode());
		SpringUtils.renderJson(response, rest);
	}

	/**
	 * 连连主动还款
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping("repay-withhold")
	public void repaymentWithhold(HttpServletResponse response, Integer id, String payPwd) {
		try {
			BorrowOrder bo = borrowOrderService.findOneBorrow(id);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("assetOrderId", bo.getId());
			Repayment re = repaymentService.findOneRepayment(map);
			User user = userService.searchByUserid(bo.getUserId());
			AESUtil aesEncrypt = new AESUtil();
			String redis_repay_id = jedisCluster.get(WITHHOLD_KEYS + "_" + re.getId());
			JsonResult rest = null;
			if ("true".equals(redis_repay_id)) {
				rest = new JsonResult("100", "交易正在处理中");
			} else if (null == user.getPayPassword()) {
				rest = new JsonResult("-101", "请从个人中心完善支付密码");
			} else if (!STATUS_HKZ.equals(re.getStatus()) && !STATUS_BFHK.equals(re.getStatus()) && !STATUS_YYQ.equals(re.getStatus())
					&& !STATUS_YHZ.equals(re.getStatus())) {
				rest = new JsonResult("-101", "本条还款不支持还款");
			} else {
				if (user.getPayPassword().equals(MD5coding.MD5(aesEncrypt.encrypt(payPwd, "")))) {
					//锁定该笔还款，防止其他渠道重复扣款，锁定时间：5分钟
					jedisCluster.setex(WITHHOLD_KEYS + "_" + re.getId(), 5 * 60, "true");
					Long money = re.getRepaymentAmount() - re.getRepaymentedAmount();
					if (money > 0) {
						ServiceResult result = repaymentService.withhold(re, user, Repayment.COLLECTION_WITHHOLD, money, OutOrders.ACT_REPAY_DEBIT);
						if (result.getCode().equals(ServiceResult.SUCCESS)) {
							rest = new JsonResult("0", "还款成功");
						} else {
							rest = new JsonResult(result.getCode(), result.getMsg());
						}

						//如果处理状态码！= 100(交易处理中)，删除redis中的该笔还款的key，防止其他渠道不能还款
						if (!"100".equals(rest.getCode())) {
							jedisCluster.del(WITHHOLD_KEYS + "_" + re.getId());
						}
						if ("-101".equals(rest.getCode()) || "-100".equals(rest.getCode())) {
							rest.setMsg("还款操作失败，请核实卡内余额及是否开通代扣");
						}
					} else {
						rest = new JsonResult("-101", "本条还款不支持还款");
					}
				} else {
					rest = new JsonResult("-103", "支付密码输入错误");
				}
			}
			SpringUtils.renderJson(response, rest);
		} catch (Exception e) {
			e.printStackTrace();
			JsonResult rest = new JsonResult("-101", "系统异常");
			SpringUtils.renderJson(response, rest);
		}

	}
	
	
	/**
	 * 由原来的访问支付路由改为 访问P2P接口，由P2P进行扣款
	 */
	public Map<String, Object> P2PDeduct(String user_apply_no, Long money,Long  remainderMoney ,String unique_mark) {
		LinkedHashMap<String, String> mapApi = SysCacheUtils.getConfigParams(BackConfigParams.YANGYUE_MDL_API);
		String url = mapApi.get(BackConfigParams.MDL_POST_URL);
		String _client_ = mapApi.get(BackConfigParams.MDL_SYS_CLIENT);
		String key = mapApi.get(BackConfigParams.MDL_SYS_KEY);
		String _cmd_ = mapApi.get(BackConfigParams.MDL_LOAN_PAYMENT);
		String _deviceid_ = mapApi.get(BackConfigParams.MDL_SYS_DEVICEID);
		String callBackUrl = mapApi.get(BackConfigParams.MDL_LOAN_PAYMENT_CALLBACK);
		
		Map<String, Object> map = new HashMap<>();
				
		//业务参数
		Payment payment = new Payment();
		payment.setUser_apply_no(user_apply_no);
		payment.setType("partial");//部分还款
		payment.setPartial_money(String.valueOf(money));//部分还款金额(单位分)，整数 ，大于 100
		payment.setRemainder_money(String.valueOf(remainderMoney));//应还金额
		payment.setCall_back_url(callBackUrl);//部分还款时传，回调地址
		payment.setUnique_mark(unique_mark);//唯一性标识 部分还款是必传	
		
		String pxh = MapConvertCoreUtils.createLinkString(MapConvertCoreUtils.paraFilter(MapConvertCoreUtils.object2Map(payment)));
		String sign = PMD5Utils.encodeByMD5(_client_ + "|" + key + "|" + _cmd_ + "|" + pxh);
		
		Map<String, Object> mm = new HashMap<String, Object>();
		mm = MapConvertCoreUtils.object2Map(payment);
		mm.put("_sign_", sign);
		mm.put("_cmd_", _cmd_);
		mm.put("_client_", _client_);
		mm.put("_deviceid_", _deviceid_);
		
		Map<String, String> w = MapConvertCoreUtils.object2MapString(mm);
		try {
//			OutOrders orders = new OutOrders();
//			orders.setStatus("0");
			//访问P2P
			logger.info("还款p2p请求参数："+w);
			String res = WebClient.getInstance().doPost(url, w);
			JSONObject json = JSONObject.fromObject(res);
			map = JSONObject.fromObject(json);
			logger.info("还款p2p返回："+json.toString());
			//记录一下out_orders表
//			orders.setUserId(userId);
//			orders.setOrderType("8");
//			orders.setAct("P2P扣款");
//			orders.setReqParams(w.toString());
//			orders.setReturnParams(res);
//			orders.setAddTime(new Date());
//			orders.setOrderNo(user_apply_no);
//			if (StringUtils.isEmpty(res)) {
//				//0请求中；1.非成功状态；2.成功(请求正常发送到第三方且被正确解析，并返回本平台),当返回参数为空并且这里是1的时候一般是请求第三方报错
//				orders.setStatus("1");
//			}else {
//				orders.setStatus("2");
//			}
//			String tablelastName = DateUtil.getDateFormat(new Date(), "yyyyMMdd");
//			orders.setTablelastName(tablelastName);
//			outOrdersService.insertByTablelastName(orders);
			
			logger.info("银行卡主动还款：访问P2P url : "+url+" 传入参数:"+w+" ，接口返回参数:"+map);
			return map;
		} catch (IOException e) {
			logger.error(e.getMessage(),e);
		}
		
		return map;
	}

	/**
	 * P2P扣款 借款人 银行卡后 回调次方法
	 */
	@RequestMapping(value = "p2pCallBack")
	public void updatePaymentCallBack(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String respCode = request.getParameter("resp_code");//返回码（0成功、1失败、2运营待审核）
		String payCutType = request.getParameter("pay_cut_type");//代扣方式（1银行卡主动还款(提前还款)、2银行卡自动扣款(到期)、3手动银行卡扣款(逾期)、4银行卡手动还款(部分还款)）
		String userApplyNo = request.getParameter("user_apply_no");//借款人申请单号
		String _sign_ = request.getParameter("_sign_");//签名
		String uniqueMark = request.getParameter("unique_mark");//借款人申请单号
		
		logger.info("银行卡主动还款：P2P回调：respCode="+respCode+" ,payCutType="+payCutType+",userApplyNo="+userApplyNo+",uniqueMark="+uniqueMark+",_sign_="+_sign_);
		JsonResult rest = new JsonResult();
		
		//验证参数
		if (StringUtils.isEmpty(respCode) || StringUtils.isEmpty(payCutType) || StringUtils.isEmpty(userApplyNo) || StringUtils.isEmpty(_sign_)) {
			rest = new JsonResult("1", "param is null");
			logger.info("银行卡主动还款：回调方法返回结果："+rest.toString());
			SpringUtils.renderJson(response, rest);
			return;
		}
		
		//效验签名
		LinkedHashMap<String, String> mapApi = SysCacheUtils.getConfigParams(BackConfigParams.YANGYUE_MDL_API);
		String key = mapApi.get(BackConfigParams.MDL_SYS_KEY);
		Map<String, String> param = getParameters(request);
		if(!PMD5Utils.checkSign(param,key)) {
			rest = new JsonResult("1", "_sign_ error");
			logger.info("银行卡主动还款：回调方法返回结果："+rest.toString());
			SpringUtils.renderJson(response, rest);
			return;
		}
		
		try {
			//查询订单是否存在
			BorrowOrder bo = borrowOrderService.findOneBorrowByOutTradeNo(userApplyNo);
			if (null == bo) {
				rest = new JsonResult("1", "user_apply_no is error");
				logger.info("银行卡主动还款：回调方法返回结果："+rest.toString());
				SpringUtils.renderJson(response, rest);
				return;
			}
			
			//查询出表的数据
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("assetOrderId", bo.getId());
			Repayment re = repaymentService.findOneRepayment(map);
			User user = userService.searchByUserid(bo.getUserId());
			UserCardInfo info = userService.findUserBankCard(bo.getUserId());
			
			
			//查询当前 uniqueMark 是否存在数据库，不存在就重新生成（只有在第14天回调时才会不存在）
			RepaymentDetail detail = repaymentDetailService.selectByOrderId(uniqueMark);
			if (null == detail) {//重新插入detail表
				RepaymentDetail repaymentDetail = new RepaymentDetail();
				repaymentDetail.setAssetRepaymentId(re.getId());
				repaymentDetail.setTrueRepaymentMoney(re.getRepaymentAmount() - re.getRepaymentedAmount());
				repaymentDetail.setRepaymentType(RepaymentDetail.TYPE_BANK_CARD);
				repaymentDetail.setUserId(bo.getUserId());
				repaymentDetail.setCreatedAt(new Date());
				repaymentDetail.setStatus(RepaymentDetail.STATUS_WAIT);
				repaymentDetail.setAssetOrderId(re.getAssetOrderId());
				repaymentDetail.setCardId(info.getId());
				repaymentDetail.setOrderId(uniqueMark);
				
				if ("0".equals(respCode)) {//成功
					repaymentService.repay(re, detail);
					if (re.getLateDay() == 0) {// 如果是未逾期的还款，调用提额
						user = userService.searchByUserid(re.getUserId());
						logger.info("repay to Mention Money ing ----------------->");
						borrowOrderService.addUserLimit(user);
					}
					
					repaymentDetail.setStatus(RepaymentDetail.STATUS_SUC);
					
					rest = new JsonResult("0", "还款成功");
				}else if ("1".equals(respCode)){//失败
					repaymentDetail.setStatus(RepaymentDetail.STATUS_OTHER);
					rest = new JsonResult("1", "还款失败");
				}
				repaymentDetailService.insertSelective(repaymentDetail);
				logger.info("银行卡主动还款：回调方法返回结果："+rest.toString());
				SpringUtils.renderJson(response, rest);
				return;
			}
			
			//如果是订单请求中就将订单状态改掉
			if (RepaymentDetail.STATUS_WAIT == detail.getStatus()) {
				RepaymentDetail newDetail = new RepaymentDetail();
				newDetail.setId(detail.getId());
				newDetail.setUpdatedAt(new Date());
				if ("0".equals(respCode)) {//成功
					repaymentService.repay(re, detail);
					if (re.getLateDay() == 0) {// 如果是未逾期的还款，调用提额
						user = userService.searchByUserid(re.getUserId());
						logger.info("repay to Mention Money ing ----------------->");
						borrowOrderService.addUserLimit(user);
					}
					
					//更新detail
					newDetail.setStatus(RepaymentDetail.STATUS_SUC);
					repaymentDetailService.updateByPrimaryKeySelective(newDetail);					
					rest = new JsonResult("0", "还款成功");
					jedisCluster.del("REPAYMENT_REPAY_WITHHOLD_"+re.getId());

				}else if ("1".equals(respCode)) {//失败
					//更新detail
					newDetail.setStatus(RepaymentDetail.STATUS_OTHER);
					repaymentDetailService.updateByPrimaryKeySelective(newDetail);
					
					rest = new JsonResult("1", "还款失败");
					jedisCluster.del("REPAYMENT_REPAY_WITHHOLD_"+re.getId());

				}
				//还款成功解除redis锁定
				logger.info("银行卡主动还款：回调方法返回结果："+rest.toString());
				SpringUtils.renderJson(response, rest);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("银行卡主动还款：P2P回调异常："+e.getMessage());
			rest = new JsonResult("-101", "系统异常");
			SpringUtils.renderJson(response, rest);
		}
	}
	
	
	
	/**
	 * 催收P2P扣款  回调次方法
	 */
	@RequestMapping(value = "overdueWithHoldCallBack")
	public void overdueWithHoldCallBack(HttpServletRequest request, HttpServletResponse response) throws IOException {
		
		LinkedHashMap<String, String> mapApi = SysCacheUtils.getConfigParams(BackConfigParams.YANGYUE_MDL_API);
		String key = mapApi.get(BackConfigParams.MDL_SYS_KEY);
		Map<String, String> param = getParameters(request);
		if(PMD5Utils.checkSign(param,key)) {
			String respCode = param.get("resp_code");//返回码（0成功、1失败、2运营待审核）
			String payCutType = param.get("pay_cut_type");//代扣方式（1银行卡主动还款、2银行卡自动扣款、3其他）
			String userApplyNo = param.get("user_apply_no");//借款人申请单号
			String uniqueMark = param.get("unique_mark");//借款人申请单号
			
			logger.info("催收代扣：P2P回调：respCode="+respCode+" ,payCutType="+payCutType+",userApplyNo="+userApplyNo+",uniqueMark="+uniqueMark);
			
			JsonResult rest = null;
			try {
				BorrowOrder bo = borrowOrderService.findOneBorrowByOutTradeNo(userApplyNo);
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("assetOrderId", bo.getId());
				Repayment re = repaymentService.findOneRepayment(map);
				User user = userService.searchByUserid(bo.getUserId());
				UserCardInfo info = userService.findUserBankCard(bo.getUserId());
				AESUtil aesEncrypt = new AESUtil();
				RepaymentDetail detail = repaymentDetailService.selectByOrderId(uniqueMark);
				if(null!=detail && RepaymentDetail.STATUS_WAIT==detail.getStatus()) {
					if ("0".equals(respCode)) {//成功
						RepaymentDetail newDetail = new RepaymentDetail();
						newDetail.setId(detail.getId());
						newDetail.setStatus(RepaymentDetail.STATUS_SUC);
						newDetail.setUpdatedAt(new Date());
						if(null != newDetail.getStatus())
							repaymentDetailService.updateByPrimaryKeySelective(newDetail);
						repaymentService.repay(re, detail);
						// 如果是未逾期的还款，调用提额
						if (re.getLateDay() == 0) {
							user = userService.searchByUserid(re.getUserId());
							logger.info("repay to Mention Money ing ----------------->");
							borrowOrderService.addUserLimit(user);
						}
						//将代扣成功告诉催收
						jedisCluster.set("WITHHOLD_"+uniqueMark, "true");
						//代扣成功解除redis锁定
						jedisCluster.del("REPAYMENT_REPAY_WITHHOLD_"+re.getId());
					}else if("1".equals(respCode)){//失败
						//将代扣失败告诉催收
						jedisCluster.set("WITHHOLD_"+uniqueMark, "fasle");
						detail.setStatus(RepaymentDetail.STATUS_OTHER);
						repaymentDetailService.updateByPrimaryKey(detail);
						rest = new JsonResult("-101", "还款失败");
						//代扣成功解除redis锁定
						jedisCluster.del("REPAYMENT_REPAY_WITHHOLD_"+re.getId());
					}
				}
				rest = new JsonResult("0", "处理成功");
			} catch (Exception e) {
				logger.error("催收代扣：P2P回调异常："+e.getMessage());
				rest = new JsonResult("-101", "系统异常");
			}
			SpringUtils.renderJson(response, rest);
		}
		
	}
	
}
